# -*- coding: utf-8 -*-
import logging

from selenium import webdriver
from selenium.webdriver.common.by import By

from utils.ClipboardUtil import Clipboard
from utils.KeyBoardUtil import KeyBoardKeys
from utils.ele_object import *
from utils.WaitUntil import WaitUntil
from utils.DirAndTime import *
from utils.RandomUtil import RandomUtil
from utils.mysql_select import MysqlSelect
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.select import Select

driver = None
wait_util = None
driver: webdriver.Chrome
wait_util: WaitUntil(driver)


# 打开浏览器
def open_browser(browser):
    global driver, wait_util
    try:
        if browser.lower() == 'ie':
            # driver = webdriver.Ie(iePath)
            driver = webdriver.Ie()
        elif browser.lower() == 'chrome':
            # driver = webdriver.Chrome(chromePath)
            driver = webdriver.Chrome()
        elif browser.lower() == 'edge':
            driver = webdriver.Edge()
        else:
            # driver = webdriver.Firefox(fireFox)
            driver = webdriver.Firefox()
    except Exception as e:
        raise e
    else:
        wait_util = WaitUntil(driver)  # driver 创建之后， 创建等待类实例对象


# 浏览器窗口最大化
def maximize_browser():
    try:
        driver.maximize_window()
    except Exception as e:
        raise e


# 加载网址
def load_url(url):
    """
    :param url: 地址
    :return:
    """
    try:
        driver.get(url)
    except Exception as e:
        raise e


# 强制等待
def sleep(sleep_seconds):
    try:
        import time
        time.sleep(sleep_seconds)
    except Exception as e:
        raise e

def _handle_calendar_picker( calendar_element, target_date):
    """处理日历控件（示例逻辑，需根据实际UI调整）"""
    # 示例：点击打开日历
    calendar_element.click()

    # 获取当前显示的年份和月份
    current_year = int(driver.find_element(By.CLASS_NAME, "ui-datepicker-year").text)
    current_month = int(driver.find_element(By.CLASS_NAME, "ui-datepicker-month").text)

    # 计算需要点击的月份差
    month_diff = (target_date.year - current_year) * 12 + (target_date.month - current_month)

    # 点击月份导航按钮
    if month_diff != 0:
        nav_button = driver.find_element(
            By.CSS_SELECTOR,
            f".ui-datepicker-{'next' if month_diff > 0 else 'prev'}"
        )
        for _ in range(abs(month_diff)):
            nav_button.click()

    # 点击目标日期
    day_element = driver.find_element(
        By.XPATH,
        f"//td[@data-handler='selectDay']/a[text()='{target_date.day}']"
    )
    day_element.click()

# 日历控件
def select_date(locator, date_str, date_format="%Y-%m-%d"):
    """
    选择日期（支持日历控件或输入框）
    :param locator: 元素定位器 (By.XPATH, By.ID等)
    :param date_str: 日期字符串，如 "2023-12-31"
    :param date_format: 日期格式，默认 "%Y-%m-%d"
    """
    try:
        date_obj = datetime.strptime(date_str, date_format)
        element = driver.find_element(*locator)

        # 如果是输入框，直接输入日期
        if element.tag_name == "input":
            element.clear()
            element.send_keys(date_str)
        # 如果是日历控件，模拟点击选择
        else:
            _handle_calendar_picker(element, date_obj)
    except Exception as e:
        raise Exception(f"选择日期失败: {e}")


# 清空输入的内容
def clear(by, locator):
    try:
        get_element(driver, by, locator).clear()
    except Exception as e:
        raise e
# 下拉框 选择value
def select_value(by,locator, value):
    alert=Select(get_element(driver, by, locator))
    alert.select_by_value(value)

# 输入框中输入内容
def input_value(by, locator, value):
    try:
        element = get_element(driver, by, locator)
        # element.click()
        element.send_keys(value)
    except Exception as e:
        raise e


def execute_script():
    import time
    # 方法一：坐标法
    driver.execute_script('window.scrollTo(0,500)')  # 横坐标不变，纵坐标 滚动到1000像素点
    time.sleep(2)  # 等待一段时间，方便查看滚动的效果


def input_random_str_value(by, locator, value, length):
    """
    输入拼接上的随机字符串的内容
    :param by: 定位方式
    :param locator: 定位元素值
    :param value: 输入内容
    :param length: 拼接随机字符串长度
    :return:
    """
    random_value = RandomUtil.generate_random_string(length)
    value = value + random_value
    try:
        element = get_element(driver, by, locator)
        # element.click()
        element.send_keys(value)
    except Exception as e:
        raise e


def input_random_int_value(by, locator, value, start, end):
    """
    拼接上的范围内的数字
    :param by: 定位方式
    :param locator: 定位元素值
    :param value: 输入内容
    :param start: 开始范围
    :param end: 结束范围
    :return:
    """
    random_value = RandomUtil.generate_random_number(start, end)
    value = value + random_value
    try:
        element = get_element(driver, by, locator)
        # element.click()
        element.send_keys(value)
    except Exception as e:
        raise e


# 点击操作
def click_btn(by, locator):
    try:
        get_element(driver, by, locator).click()
    except Exception as e:
        raise e


# 断言页面的title
def assert_title(title_str):
    try:
        assert title_str in driver.title, "%s not found in title!" % title_str
    except AssertionError as e:
        raise AssertionError(e)
    except Exception as e:
        raise e


# 断言目标字符串是否包含在页面源码中
def assert_string_in_page_source(assert_string):
    try:
        assert assert_string in driver.page_source, "%s not found in page source!" % assert_string
    except AssertionError as e:
        raise AssertionError(e)
    except Exception as e:
        raise e


# 获取当前页面的title
def get_title():
    try:
        return driver.title
    except Exception as e:
        raise e


# 获取页面源码
def get_page_source():
    try:
        return driver.page_source
    except Exception as e:
        raise e


# 切换到frame里面
def switch_to_frame(by, locator):
    try:
        driver.switch_to.frame(get_element(driver, by, locator))
    except Exception as e:
        raise e


# 跳到默认的frame
def switch_to_default():
    try:
        driver.switch_to.default_content()
    except Exception as e:
        raise e


# 模拟ctrl+v键
def ctrl_v(value):
    try:
        Clipboard.set_text(value)
        sleep(2)
        KeyBoardKeys.two_keys('ctrl', 'v')
    except Exception as e:
        raise e


# 模拟tab键
def tab_key():
    try:
        KeyBoardKeys.one_key('tab')
    except Exception as e:
        raise e


# 模拟enter键
def enter_key():
    try:
        KeyBoardKeys.one_key('enter')
    except Exception as e:
        raise e





# 屏幕截图
def save_screen_shot():
    picture_name = DirAndTime.create_picture_path() + '\\' + DirAndTime.get_current_time() + '.png'
    try:
        driver.get_screenshot_as_file(picture_name)
    except Exception as e:
        raise e
    else:
        return picture_name


def wait_presence_of_element_located(by, locator):
    """
    显示等待页面元素出现在DOM中，不一定可见
    :param by:
    :param locator:
    :return:
    """
    wait_util.presence_of_element_located(by, locator)


def wait_frame_to_be_available_and_switch_to_it(by, locator):
    """
    检查frame是否存在，存在就切换到frame中
    :param by:
    :param locator:
    :return:
    """
    wait_util.frame_to_be_available_and_switch_to_it(by, locator)


def wait_visibility_of_element_located(by, locator):
    """
    显示等待页面元素出现在DOM中，并且可见
    :param by:
    :param locator:
    :return:
    """
    wait_util.visibility_of_element_located(by, locator)


# 关闭浏览器
def quit_browser():
    try:
        driver.quit()
    except Exception as e:
        raise e


def assert_mysql_first_value(table, key_data=None, value_data=None, param=None, assert_value=None):
    """
    断言单条数据, 获取对应的字段的值
    :param table: 表名
    :param key_data: 判断的字段名用[]传入，[字段1,字段2,字段3]
    :param value_data: 判断的字段值用[]传入，[值1,值2,值3]
    :param param: 你所要获取到字段的条件
    :param assert_value: 要断言的值
    :return:
    """
    if key_data:
        # key_data = [f'{key_data}']
        key_data = key_data

    if value_data:
        # value_data = [f'{value_data}']
        value_data = value_data
    result = MysqlSelect().mysql_select_first(table, key_data, value_data, param)
    assert assert_value == result, f'预期结果是：{assert_value},实际结果是：{result},断言不通过'
    logging.info(f'预期结果是：{assert_value},实际结果是：{result},断言通过')


def assert_mysql_length(table, key_data=None, value_data=None, assert_value=None):
    """
    断言获取到符合条件数据的数量
    :param table: 表名
    :param key_data: 判断的字段名用[]传入，[字段1,字段2,字段3]
    :param value_data: 判断的字段值用[]传入，[值1,值2,值3]
    :param assert_value: 预期长度
    :return:
    """
    if key_data:
        # key_data = [f'{key_data}']
        key_data = key_data

    if value_data:
        # value_data = [f'{value_data}']
        value_data = value_data

    result = MysqlSelect().mysql_length(table, key_data, value_data)
    assert assert_value == result, f'预期存在数据数量：{assert_value},实际存在数据数量：{result},断言不通过'
    logging.info(f'预期存在数据数量：{assert_value},实际存在数据数量：{result},断言通过')


if __name__ == '__main__':
    from time import sleep

    # open_browser('firefox')
    # load_url('http://www.baidu.com')
    # input_value('id', 'kw', 'python')
    # clear('id', 'kw')
    # input_value('id', 'kw', 'python')
    # click_btn('id', 'su')
    # sleep(3)
    # title = get_title()
    # print(title)
    # assert_title('python')
    # assert_string_in_page_source('python')
    # # ctrl_v('python')
    # sleep(3)
    # quite_browser()

    # assert_mysql_first_value('y_user', "username", "admin", 'pwd', 'ebcbf97ec1d80c0388d39bf508039baa')
    assert_mysql_first_value('area', ["name", "sort"], ['上地', '2'], 'atype', 2)
    # assert_mysql_length('y_user', "username", "admin", 1)
    assert_mysql_length('area', ["name", "sort"], ["上地", '2'], 1)
